<template>
  <div class="container">
    <div class="notification" :class="{ show, error }">{{ notificationMessage }}</div>

    <header>
      <h1>学生座位表调整工具</h1>
      <div class="subtitle">自定义布局 | 拖拽交换 | Excel导入/导出</div>
    </header>

    <div class="toolbar">
      <div class="file-upload">
        <button class="btn">
          <i>📊</i> 导入Excel
          <input type="file" id="excel-file" accept=".xlsx, .xls" @change="handleExcelImport">
        </button>
      </div>

      <div class="btn-group">
        <button class="btn btn-random" @click="randomizeSeats">
          <i>🔀</i> 随机排列
        </button>
        <button class="btn btn-reset" @click="resetSeats">
          <i>🔄</i> 重置座位
        </button>
        <button class="btn btn-pdf" @click="exportToPdf">
          <i>📄</i> 导出PDF
        </button>
        <button class="btn btn-excel" @click="exportToExcel">
          <i>📤</i> 导出Excel
        </button>
        <button class="btn" @click="showLayoutModal = true">
          <i>🔲</i> 设置布局
        </button>
      </div>
    </div>

    <div class="classroom-container" id="print-target">
      <div class="classroom-header">教室座位布局（<span id="layout-info">{{ rows }}×{{ columns }}标准座位</span>）</div>
      <div class="classroom" id="classroom" :style="{ gridTemplateColumns: `repeat(${columns}, 1fr)` }">

        <!-- 普通座位 -->
        <div
            class="seat"
            :class="{
            empty: seat.isEmpty,
            male: !seat.isEmpty && seat.gender === '男',
            female: !seat.isEmpty && seat.gender === '女',
            dragging: draggedSeat?.id === seat.id,
            'drag-over': dragOverSeat?.id === seat.id
          }"
            :data-id="seat.id"
            draggable="true"
            @dragstart="handleDragStart(seat, $event)"
            @dragover.prevent
            @dragenter.prevent="handleDragEnter(seat)"
            @dragleave="handleDragLeave(seat)"
            @drop.prevent="handleDrop(seat)"
            @dragend="handleDragEnd"
            v-for="seat in seats" :key="seat.id"
        >
          <div class="seat-position">{{ seat.id }}</div>
          <div class="student-name">{{ seat.isEmpty ? '空' : seat.name }}</div>
          <template v-if="!seat.isEmpty">
            <div class="student-details">
              <div class="student-gender">{{ seat.gender }}</div>
            </div>
          </template>
        </div>
      </div>
    </div>

    <div class="status-bar">
      <div class="stats-container">
        <div class="stats-box male">
          <div class="stats-title">男生人数</div>
          <div class="stats-value">{{ maleCount }}</div>
        </div>
        <div class="stats-box female">
          <div class="stats-title">女生人数</div>
          <div class="stats-value">{{ femaleCount }}</div>
        </div>
        <div class="stats-box empty">
          <div class="stats-title">空座位数</div>
          <div class="stats-value">{{ emptyCount }}</div>
        </div>
        <div class="stats-box total">
          <div class="stats-title">学生总数</div>
          <div class="stats-value">{{ studentCount }}</div>
        </div>
        <div class="stats-box">
          <div class="stats-title">总座位数</div>
          <div class="stats-value">{{ totalSeats }}</div>
        </div>
      </div>
    </div>

    <div class="instructions">
      <h2>使用说明</h2>
      <ul>
        <li><strong>座位布局</strong>：讲台居中，下方为自定义布局（默认8×8，共64个座位）</li>
        <li><strong>Excel导入</strong>：点击"导入Excel"按钮，选择包含学生信息的Excel文件（包含"姓名"、"性别"列）</li>
        <li><strong>Excel导出</strong>：点击"导出Excel"按钮将当前座位表导出为Excel文件</li>
        <li><strong>拖拽交换</strong>：拖动学生座位到另一个座位进行交换（可以与空位交换）</li>
        <li><strong>随机排列</strong>：点击"随机排列"按钮打乱当前学生座位顺序</li>
        <li><strong>本地存储</strong>：座位表状态会自动保存，刷新页面不会丢失数据</li>
        <li><strong>重置座位</strong>：点击"重置"按钮清空所有座位</li>
        <li><strong>导出PDF</strong>：点击"导出PDF"按钮生成当前座位表的PDF文件</li>
        <li><strong>设置布局</strong>：点击"设置布局"按钮自定义普通座位区的行数和列数</li>
      </ul>
    </div>

    <!-- 自定义布局弹窗 -->
    <div class="modal" :class="{ active: showLayoutModal }" @click="closeLayoutModalOnOutside">
      <div class="modal-content" @click.stop>
        <div class="modal-header">
          <div class="modal-title">设置座位布局</div>
          <div class="close-modal" @click="showLayoutModal = false">&times;</div>
        </div>
        <div class="modal-body">
          <div class="form-group">
            <label for="rows">行数：</label>
            <input type="number" id="rows" v-model.number="newRows" min="1" max="20" placeholder="输入行数">
          </div>
          <div class="form-group">
            <label for="columns">列数：</label>
            <input type="number" id="columns" v-model.number="newColumns" min="1" max="20" placeholder="输入列数">
          </div>
        </div>
        <div class="modal-footer">
          <button class="btn btn-cancel" @click="showLayoutModal = false">取消</button>
          <button class="btn" @click="confirmLayout">确认</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch } from 'vue';
import * as XLSX from 'xlsx';
import { jsPDF } from 'jspdf';
import html2canvas from 'html2canvas';

// 状态变量
const rows = ref(8);
const columns = ref(8);
const newRows = ref(8);
const newColumns = ref(8);
const showLayoutModal = ref(false);
const seats = ref([]);
const draggedSeat = ref(null);
const dragOverSeat = ref(null);
const notificationMessage = ref('');
const showNotification = ref(false);
const notificationError = ref(false);

// 计算属性
const totalSeats = computed(() => rows.value * columns.value);
const maleCount = computed(() => seats.value.filter(seat => !seat.isEmpty && seat.gender === '男').length);
const femaleCount = computed(() => seats.value.filter(seat => !seat.isEmpty && seat.gender === '女').length);
const studentCount = computed(() => maleCount.value + femaleCount.value);
const emptyCount = computed(() => totalSeats.value - studentCount.value);

// 初始化座位
function initSeats() {
  seats.value = Array(totalSeats.value).fill().map((_, index) => ({
    id: index + 1,
    name: "",
    gender: "",
    isEmpty: true
  }));
}

// 从本地存储加载
function loadFromLocalStorage() {
  const savedSeats = localStorage.getItem('classroomSeats');
  const savedLayout = localStorage.getItem('classroomLayout');

  if (savedLayout) {
    try {
      const { r, c } = JSON.parse(savedLayout);
      if (typeof r === 'number' && typeof c === 'number') {
        rows.value = r;
        columns.value = c;
        newRows.value = r;
        newColumns.value = c;
      }
    } catch (e) {
      console.error("解析布局数据失败:", e);
    }
  }

  if (savedSeats) {
    try {
      const parsedSeats = JSON.parse(savedSeats);
      if (Array.isArray(parsedSeats) && parsedSeats.length === totalSeats.value) {
        seats.value = parsedSeats;
        showNotificationMessage("已加载上次保存的座位表");
        return true;
      }
    } catch (e) {
      console.error("解析本地存储数据失败:", e);
    }
  }
  return false;
}

// 保存到本地存储
function saveToLocalStorage() {
  localStorage.setItem('classroomSeats', JSON.stringify(seats.value));
  localStorage.setItem('classroomLayout', JSON.stringify({
    r: rows.value,
    c: columns.value
  }));
}

// 显示通知
function showNotificationMessage(message, isError = false) {
  notificationMessage.value = message;
  notificationError.value = isError;
  showNotification.value = true;

  setTimeout(() => {
    showNotification.value = false;
  }, 3000);
}

// 处理拖拽事件
function handleDragStart(seat, event) {
  // 空位不能拖动
  if (seat.isEmpty) {
    event.preventDefault();
    return;
  }

  draggedSeat.value = seat;
  // 添加拖拽数据以确保拖拽功能正常工作
  event.dataTransfer.setData('text/plain', seat.id.toString());
  // 延迟添加拖拽类以确保视觉效果正确
  setTimeout(() => {
    const element = event.target.closest('.seat');
    if (element) element.classList.add('dragging');
  }, 0);
}

function handleDragEnter(seat) {
  if (!draggedSeat.value || draggedSeat.value.id === seat.id) return;
  dragOverSeat.value = seat;
}

function handleDragLeave(seat) {
  if (dragOverSeat.value?.id === seat.id) {
    dragOverSeat.value = null;
  }
}

function handleDrop(targetSeat) {
  if (!draggedSeat.value || draggedSeat.value.id === targetSeat.id) return;

  if (targetSeat.isEmpty) {
    // 移动到空位
    targetSeat.name = draggedSeat.value.name;
    targetSeat.gender = draggedSeat.value.gender;
    targetSeat.isEmpty = false;

    // 清空原座位
    draggedSeat.value.name = "";
    draggedSeat.value.gender = "";
    draggedSeat.value.isEmpty = true;
  } else {
    // 交换座位
    [draggedSeat.value.name, targetSeat.name] = [targetSeat.name, draggedSeat.value.name];
    [draggedSeat.value.gender, targetSeat.gender] = [targetSeat.gender, draggedSeat.value.gender];
  }

  dragOverSeat.value = null;
  saveToLocalStorage();
  showNotificationMessage("座位调整成功！");
}

function handleDragEnd(event) {
  // 移除所有拖拽相关的类
  const elements = document.querySelectorAll('.seat');
  elements.forEach(el => {
    el.classList.remove('dragging', 'drag-over');
  });

  draggedSeat.value = null;
  dragOverSeat.value = null;
}

// 处理Excel导入
function handleExcelImport(e) {
  const file = e.target.files[0];
  if (!file) return;

  // 重置文件输入，允许重复选择同一文件
  const input = document.getElementById('excel-file');
  if (input) input.value = '';

  const reader = new FileReader();
  reader.onload = function(e) {
    try {
      const data = new Uint8Array(e.target.result);
      const workbook = XLSX.read(data, { type: 'array' });

      // 获取第一个工作表
      const worksheet = workbook.Sheets[workbook.SheetNames[0]];
      const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });

      // 处理数据
      const students = [];
      let nameIndex = -1, genderIndex = -1;

      // 查找列索引
      if (jsonData.length > 0) {
        const headerRow = jsonData[0];
        nameIndex = headerRow.findIndex(cell =>
            cell && String(cell).toLowerCase().includes("姓名") ||
            String(cell).toLowerCase().includes("名字")
        );
        genderIndex = headerRow.findIndex(cell =>
            cell && String(cell).toLowerCase().includes("性别")
        );

        // 如果未找到姓名列，尝试使用第一列
        if (nameIndex === -1) {
          nameIndex = 0;
          showNotificationMessage("未找到'姓名'列，将使用第一列作为姓名", false);
        }
      }

      // 处理学生数据
      for (let i = 1; i < jsonData.length; i++) {
        const row = jsonData[i];
        if (!row || row.length === 0) continue;

        const student = {
          name: nameIndex >= 0 && row[nameIndex] ? String(row[nameIndex]).trim() : "",
          gender: genderIndex >= 0 && row[genderIndex] ? String(row[genderIndex]).trim() : ""
        };

        if (student.name) {
          students.push(student);
        }
      }

      if (students.length === 0) {
        showNotificationMessage("Excel中没有找到有效的学生数据，请检查格式", true);
        return;
      }

      // 重置座位并填充新数据
      initSeats();

      // 填充学生数据
      let seatIndex = 0;
      students.forEach(student => {
        if (seatIndex < seats.value.length) {
          seats.value[seatIndex].name = student.name;
          seats.value[seatIndex].gender = student.gender;
          seats.value[seatIndex].isEmpty = false;
          seatIndex++;
        }
      });

      saveToLocalStorage();
      showNotificationMessage(`成功导入 ${students.length} 名学生数据`);
    } catch (error) {
      console.error("Excel导入错误:", error);
      showNotificationMessage(`Excel导入失败: ${error.message}`, true);
    }
  };

  reader.onerror = function() {
    showNotificationMessage("文件读取失败，请尝试其他文件", true);
  };

  reader.readAsArrayBuffer(file);
}

// 导出Excel
function exportToExcel() {
  try {
    // 准备数据
    const data = [];

    // 添加标题行
    data.push(['学生座位表（姓名）']);
    data.push([]); // 空行

    // 添加普通座位区标题
    data.push(['普通座位区']);

    // 添加列标题
    const columnHeaders = ['行\\列'];
    for (let col = 1; col <= columns.value; col++) {
      columnHeaders.push(`第${col}列`);
    }
    data.push(columnHeaders);

    // 添加每行数据
    for (let row = 0; row < rows.value; row++) {
      const rowData = [`第${row + 1}行`];

      for (let col = 0; col < columns.value; col++) {
        const seatIndex = row * columns.value + col;
        const seat = seats.value[seatIndex];
        rowData.push(seat?.isEmpty ? '空' : seat?.name || '空');
      }

      data.push(rowData);
    }

    // 创建工作簿
    const ws = XLSX.utils.aoa_to_sheet(data);
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "座位表");

    // 设置列宽
    const colWidths = [{ wch: 8 }];
    for (let i = 1; i <= columns.value; i++) {
      colWidths.push({ wch: 12 });
    }
    ws['!cols'] = colWidths;

    // 合并标题单元格
    ws['!merges'] = [
      { s: { r: 0, c: 0 }, e: { r: 0, c: columns.value } },
      { s: { r: 2, c: 0 }, e: { r: 2, c: columns.value } }
    ];

    // 导出
    XLSX.writeFile(wb, "学生座位表.xlsx");
    showNotificationMessage("Excel导出成功！");
  } catch (error) {
    console.error("导出Excel时出错:", error);
    showNotificationMessage("导出Excel失败，请重试", true);
  }
}

// 随机排列
function randomizeSeats() {
  const nonEmptySeats = seats.value.filter(seat => !seat.isEmpty);

  if (nonEmptySeats.length === 0) {
    showNotificationMessage("没有学生数据，无法随机排列", true);
    return;
  }

  // 随机打乱顺序
  for (let i = nonEmptySeats.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [nonEmptySeats[i].name, nonEmptySeats[j].name] = [nonEmptySeats[j].name, nonEmptySeats[i].name];
    [nonEmptySeats[i].gender, nonEmptySeats[j].gender] = [nonEmptySeats[j].gender, nonEmptySeats[i].gender];
  }

  saveToLocalStorage();
  showNotificationMessage("座位随机排列完成");
}

// 重置座位
function resetSeats() {
  if (confirm("确定要重置所有座位吗？这将清除所有学生数据。")) {
    initSeats();
    saveToLocalStorage();
    showNotificationMessage("座位表已重置");
  }
}

// 导出PDF（只包含座位）
function exportToPdf() {
  const classroomElement = document.getElementById('classroom');

  if (!classroomElement) {
    showNotificationMessage("找不到座位表内容", true);
    return;
  }

  showNotificationMessage("正在生成PDF，请稍候...");

  // 创建临时容器
  const tempContainer = document.createElement('div');
  tempContainer.style.width = '100%';
  tempContainer.style.background = '#fff';
  tempContainer.style.padding = '20px';
  tempContainer.style.boxSizing = 'border-box';

  // 克隆座位区域
  const clonedContent = classroomElement.cloneNode(true);

  // 调整样式
  clonedContent.style.gap = '8px';
  clonedContent.style.padding = '15px';

  // 调整座位样式
  const allSeats = clonedContent.querySelectorAll('.seat');
  allSeats.forEach(seat => {
    seat.style.height = '70px';
    seat.style.padding = '8px';

    const nameElement = seat.querySelector('.student-name');
    if (nameElement) {
      nameElement.style.fontSize = '12px';
      nameElement.style.fontWeight = 'bold';
      nameElement.style.color = '#000';
    }

    const genderElements = seat.querySelectorAll('.student-gender');
    genderElements.forEach(el => {
      el.style.fontSize = '10px';
      el.style.color = '#000';
    });
  });

  // 添加标题
  const title = document.createElement('h2');
  title.style.textAlign = 'center';
  title.style.margin = '0 0 20px 0';
  title.style.fontSize = '18px';
  title.textContent = '学生座位表';

  // 组装临时容器
  tempContainer.appendChild(title);
  tempContainer.appendChild(clonedContent);

  // 添加到页面但隐藏
  tempContainer.style.position = 'absolute';
  tempContainer.style.top = '-10000px';
  tempContainer.style.left = '-10000px';
  document.body.appendChild(tempContainer);

  // 生成PDF
  const useLandscape = columns.value > 8;
  const pdf = new jsPDF({
    orientation: useLandscape ? 'landscape' : 'portrait',
    unit: 'mm',
    format: 'a4'
  });

  html2canvas(tempContainer, {
    scale: 3,
    useCORS: true,
    logging: false,
    scrollY: -window.scrollY,
    windowWidth: tempContainer.offsetWidth,
    letterRendering: true,
    backgroundColor: null
  }).then(canvas => {
    const imgWidth = useLandscape ? 270 : 190;
    const imgHeight = canvas.height * imgWidth / canvas.width;
    const marginX = useLandscape ? 10 : 10;
    const marginY = 10;

    // 处理多页
    const pageHeight = useLandscape ? 180 : 270;
    let position = marginY;

    if (imgHeight > pageHeight - marginY * 2) {
      let heightLeft = imgHeight;
      let startY = 0;

      while (heightLeft > 0) {
        const pageHeightCurrent = heightLeft > pageHeight ? pageHeight : heightLeft;

        const canvasData = canvas.getContext('2d').getImageData(
            0,
            startY,
            canvas.width,
            canvas.height * pageHeightCurrent / imgHeight
        );

        const newCanvas = document.createElement('canvas');
        newCanvas.width = canvas.width;
        newCanvas.height = canvas.height * pageHeightCurrent / imgHeight;
        newCanvas.getContext('2d').putImageData(canvasData, 0, 0);

        const imgData = newCanvas.toDataURL('image/png');

        pdf.addImage(imgData, 'PNG', marginX, position, imgWidth, pageHeightCurrent);

        heightLeft -= pageHeightCurrent;
        startY += canvas.height * pageHeightCurrent / imgHeight;
        position = marginY;

        if (heightLeft > 0) {
          pdf.addPage();
        }
      }
    } else {
      const imgData = canvas.toDataURL('image/png');
      pdf.addImage(imgData, 'PNG', marginX, marginY, imgWidth, imgHeight);
    }

    pdf.save('学生座位表.pdf');
    document.body.removeChild(tempContainer);
    showNotificationMessage("PDF导出成功！");
  }).catch(error => {
    console.error("PDF导出错误:", error);
    showNotificationMessage("PDF导出失败，请重试", true);
    document.body.removeChild(tempContainer);
  });
}

// 布局设置
function confirmLayout() {
  if (isNaN(newRows.value) || isNaN(newColumns.value) ||
      newRows.value < 1 || newColumns.value < 1 ||
      newRows.value > 20 || newColumns.value > 20) {
    showNotificationMessage("请输入有效的行数和列数（1-20之间）", true);
    return;
  }

  // 保存当前学生数据
  const currentStudents = seats.value.filter(seat => !seat.isEmpty);

  // 更新布局
  rows.value = newRows.value;
  columns.value = newColumns.value;

  // 初始化新座位
  initSeats();

  // 恢复学生数据
  let seatIndex = 0;
  currentStudents.forEach(student => {
    if (seatIndex < seats.value.length) {
      seats.value[seatIndex].name = student.name;
      seats.value[seatIndex].gender = student.gender;
      seats.value[seatIndex].isEmpty = false;
      seatIndex++;
    }
  });

  saveToLocalStorage();
  showLayoutModal.value = false;
  showNotificationMessage(`座位布局已更新为 ${rows.value}×${columns.value}`);
}

function closeLayoutModalOnOutside(e) {
  if (e.target === e.currentTarget) {
    showLayoutModal.value = false;
  }
}

// 初始化
onMounted(() => {
  initSeats();
  loadFromLocalStorage();

  // 监听布局变化
  watch([rows, columns], () => {
    initSeats();
  });
});
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}

body {
  background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
  min-height: 100vh;
  padding: 20px;
  color: #333;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
}

header {
  text-align: center;
  padding: 25px 0;
  margin-bottom: 30px;
  background: linear-gradient(90deg, #1a73e8, #0d47a1);
  color: white;
  border-radius: 12px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}

h1 {
  font-size: 2.6rem;
  margin-bottom: 10px;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.25);
}

.subtitle {
  font-size: 1.15rem;
  opacity: 0.92;
  letter-spacing: 0.5px;
}

.toolbar {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 18px;
  padding: 22px;
  background: linear-gradient(135deg, #ffffff, #f8f9fa);
  border-radius: 12px;
  box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
  margin-bottom: 30px;
  border: 1px solid #e1e5eb;
}

.btn-group {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

.btn {
  padding: 14px 28px;
  background: linear-gradient(135deg, #4285f4, #1a73e8);
  color: white;
  border: none;
  border-radius: 50px;
  cursor: pointer;
  font-weight: 600;
  font-size: 1.05rem;
  transition: all 0.3s ease;
  box-shadow: 0 5px 12px rgba(66, 133, 244, 0.35);
  display: flex;
  align-items: center;
  gap: 10px;
}

.btn:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 15px rgba(66, 133, 244, 0.45);
}

.btn:active {
  transform: translateY(1px);
  box-shadow: 0 3px 8px rgba(66, 133, 244, 0.35);
}

.btn-random {
  background: linear-gradient(135deg, #fbbc05, #e6a000);
  box-shadow: 0 5px 12px rgba(251, 188, 5, 0.35);
}

.btn-reset {
  background: linear-gradient(135deg, #ea4335, #d32d20);
  box-shadow: 0 5px 12px rgba(234, 67, 53, 0.35);
}

.btn-pdf {
  background: linear-gradient(135deg, #e53935, #b71c1c);
  box-shadow: 0 5px 12px rgba(229, 57, 53, 0.35);
}

.btn-excel {
  background: linear-gradient(135deg, #0f9d58, #0b8043);
  box-shadow: 0 5px 12px rgba(15, 157, 88, 0.35);
}

.file-upload {
  position: relative;
  display: inline-block;
  overflow: hidden;
  border-radius: 50px;
  box-shadow: 0 4px 10px rgba(66, 133, 244, 0.3);
}

.file-upload input {
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
  cursor: pointer;
}

/* 教室布局 */
.classroom-container {
  background: white;
  border-radius: 14px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12);
  overflow: hidden;
  margin-bottom: 30px;
  border: 1px solid #e9ecef;
}

.classroom-header {
  background: linear-gradient(135deg, #6a11cb, #2575fc);
  color: white;
  text-align: center;
  padding: 15px;
  font-weight: bold;
  font-size: 1.2rem;
}

.classroom {
  display: grid;
  gap: 14px;
  padding: 25px;
}

/* 讲台容器 */
.teacher-desk-container {
  grid-column: 1 / -1;
  display: flex;
  justify-content: center;
  margin-bottom: 25px;
}

/* 讲台 */
.teacher-desk {
  width: 300px;
  background: linear-gradient(135deg, #8e2de2, #4a00e0);
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  font-size: 1.3rem;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
  text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
  padding: 15px;
}

/* 普通座位样式 */
.seat {
  height: 120px;
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 12px;
  cursor: move;
  transition: all 0.3s ease;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
  position: relative;
  overflow: hidden;
  border: 2px solid transparent;
}

.seat.empty {
  background: linear-gradient(135deg, #f0f0f0, #e0e0e0);
  color: #999;
}

.seat.male {
  background: linear-gradient(135deg, #64b5f6, #42a5f5);
  border-color: #bbdefb;
}

.seat.female {
  background: linear-gradient(135deg, #f48fb1, #f06292);
  border-color: #f8bbd0;
}

.seat.dragging {
  opacity: 0.7;
  transform: scale(0.95);
  box-shadow: 0 0 20px rgba(66, 133, 244, 0.7);
  z-index: 10;
}

.seat.drag-over {
  background-color: rgba(255, 235, 59, 0.4) !important;
  transform: scale(1.06);
  border-color: #ffc107 !important;
}

/* 位置信息样式 */
.seat-position {
  position: absolute;
  top: 8px;
  left: 8px;
  font-size: 0.85rem;
  font-weight: 700;
  color: #555;
  background: rgba(255, 255, 255, 0.7);
  border-radius: 20px;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 姓名样式 */
.student-name {
  font-size: 1.25rem;
  font-weight: 700;
  margin-bottom: 8px;
  text-align: center;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0 5px;
}

/* 性别容器 */
.student-details {
  display: flex;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 0 5px;
}

/* 性别样式 */
.student-gender {
  font-size: 0.9rem;
  padding: 3px 10px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.4);
  font-weight: 600;
  white-space: nowrap;
}

.instructions {
  background: linear-gradient(135deg, #ffffff, #f8f9fa);
  padding: 28px;
  border-radius: 14px;
  box-shadow: 0 6px 15px rgba(0, 0, 0, 0.08);
  margin-top: 25px;
  border: 1px solid #e9ecef;
}

.instructions h2 {
  color: #1a73e8;
  margin-bottom: 20px;
  font-size: 1.6rem;
  text-align: center;
  padding-bottom: 12px;
  border-bottom: 2px solid #e0e7ff;
}

.instructions ul {
  padding-left: 30px;
  line-height: 1.85;
}

.instructions li {
  margin-bottom: 14px;
  font-size: 1.05rem;
  position: relative;
}

.instructions li:before {
  content: "•";
  color: #1a73e8;
  font-weight: bold;
  display: inline-block;
  width: 1em;
  margin-left: -1em;
  font-size: 1.3rem;
}

.status-bar {
  display: flex;
  justify-content: space-between;
  padding: 18px 25px;
  background: linear-gradient(135deg, #ffffff, #f8f9fa);
  border-radius: 14px;
  box-shadow: 0 6px 15px rgba(0, 0, 0, 0.08);
  margin-top: 25px;
  font-size: 1rem;
  border: 1px solid #e9ecef;
  flex-wrap: wrap;
  gap: 12px;
}

.stats-container {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  width: 100%;
  justify-content: center;
}

.stats-box {
  background: rgba(255, 255, 255, 0.7);
  border-radius: 10px;
  padding: 12px 20px;
  min-width: 160px;
  text-align: center;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.stats-title {
  font-size: 0.9rem;
  color: #666;
  margin-bottom: 6px;
}

.stats-value {
  font-size: 1.4rem;
  font-weight: bold;
  color: #1a73e8;
}

.stats-box.male .stats-value {
  color: #4285f4;
}

.stats-box.female .stats-value {
  color: #f06292;
}

.stats-box.empty .stats-value {
  color: #666;
}

.stats-box.total .stats-value {
  color: #0f9d58;
}

.notification {
  position: fixed;
  top: 20px;
  right: 20px;
  padding: 15px 25px;
  background: #4CAF50;
  color: white;
  border-radius: 8px;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
  z-index: 1000;
  transform: translateX(150%);
  transition: transform 0.3s ease;
}

.notification.show {
  transform: translateX(0);
}

.notification.error {
  background: #f44336;
}

/* 自定义布局弹窗 */
.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 2000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

.modal.active {
  opacity: 1;
  pointer-events: auto;
}

.modal-content {
  background-color: white;
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  max-width: 400px;
  width: 90%;
  padding: 30px;
  transform: scale(0.9);
  transition: transform 0.3s ease;
}

.modal.active .modal-content {
  transform: scale(1);
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.modal-title {
  font-size: 1.5rem;
  font-weight: bold;
  color: #1a73e8;
}

.close-modal {
  font-size: 1.5rem;
  cursor: pointer;
  color: #666;
  transition: color 0.3s ease;
}

.close-modal:hover {
  color: #333;
}

.form-group {
  margin-bottom: 20px;
}

.form-group label {
  display: block;
  font-size: 1.1rem;
  margin-bottom: 8px;
  color: #333;
}

.form-group input {
  width: 100%;
  padding: 12px;
  border: 1px solid #ddd;
  border-radius: 8px;
  font-size: 1rem;
  transition: border-color 0.3s ease;
}

.form-group input:focus {
  border-color: #1a73e8;
  outline: none;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 15px;
}

.btn-cancel {
  background: linear-gradient(135deg, #f0f0f0, #e0e0e0);
  color: #333;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}

.btn-cancel:hover {
  background: linear-gradient(135deg, #e0e0e0, #d0d0d0);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
}

/* 响应式设计 */
@media (max-width: 900px) {
  .classroom {
    gap: 12px;
  }

  .toolbar {
    flex-direction: column;
    align-items: center;
  }

  .btn-group {
    width: 100%;
    justify-content: center;
  }

  .status-bar {
    flex-wrap: wrap;
    gap: 12px;
    justify-content: center;
  }

  .stats-container {
    flex-wrap: wrap;
  }

  .student-name {
    font-size: 1.1rem;
  }

  .student-gender {
    font-size: 0.8rem;
    padding: 2px 8px;
  }
}

@media (max-width: 600px) {
  .classroom {
    grid-template-columns: repeat(2, 1fr);
  }

  .teacher-desk {
    width: 100%;
  }

  header h1 {
    font-size: 2rem;
  }

  .btn {
    padding: 12px 20px;
    font-size: 0.95rem;
  }

  .stats-container {
    flex-direction: column;
    align-items: center;
  }

  .stats-box {
    width: 100%;
  }

  .modal-content {
    max-width: 90%;
    padding: 20px;
  }

  .seat {
    height: 110px;
  }

  .student-name {
    font-size: 1rem;
  }
}

/* PDF打印专用样式 */
@media print {
  body * {
    visibility: hidden;
  }

  .print-container,
  .print-container * {
    visibility: visible;
  }

  .print-container {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
  }
}
</style>
